package com.pesoexpress.util;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.util.Date;

import org.jpos.iso.ISOChannel;
import org.jpos.iso.ISODate;
import org.jpos.iso.ISOException;
import org.jpos.iso.ISOMsg;
import org.jpos.iso.ISOUtil;
import org.jpos.iso.channel.ASCIIChannel;
import org.jpos.iso.packager.ISO87APackager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.pesoexpress.operations.schema.PesoExpressReq;
import com.pesoexpress.operations.schema.PesoExpressResp;

public class PesoExpressISOUtils {

	private static final Logger LOGGER = LoggerFactory.getLogger(PesoExpressISOUtils.class);
	
	public static PesoExpressResp sendEnvio(PesoExpressReq req, String host, int port) throws ISOException, IOException{
		ISOMsg m = createIsoMessage0200(req);
		ISOMsg r = sendMessage(m, host, port);
		PesoExpressResp resp = createResponse(r);
		return resp;
	}
	
	public static PesoExpressResp sendRetiro(PesoExpressReq req, String host, int port) throws ISOException, IOException{
		ISOMsg m = createIsoMessage0200(req);
		ISOMsg r = sendMessage(m, host, port);
		PesoExpressResp resp = createResponse(r);
		return resp;
	}
	
	public static PesoExpressResp sendReverso(PesoExpressReq req, String host, int port) throws ISOException, IOException{
		ISOMsg m = createIsoMessage0420(req);
		ISOMsg r = sendMessage(m, host, port);
		PesoExpressResp resp = createResponse(r);
		return resp;
	}
	
	public static PesoExpressResp msgError(){
		PesoExpressResp r = new PesoExpressResp();
		r.setF39("99");
		return r;
	}
	
	private static ISOMsg sendMessage(ISOMsg m, String host, int port) throws IOException, ISOException{
		ISOChannel channel = new ASCIIChannel(host, port,
				new ISO87APackager());
		channel.connect();
		channel.send(m);
		logMessage(m);
		ISOMsg r = channel.receive();
		logMessage(r);
		channel.disconnect();
		return r;
	}
	
	private static void logMessageRaw(ISOMsg m) throws IOException, ISOException{
		ByteArrayOutputStream os = new ByteArrayOutputStream();
		m.pack(os);
		String message = os.toString();
		System.out.println(message);
		os.close();
	}
	
	private static void logMessage(ISOMsg m){
		LOGGER.debug("Message formatted");
		ByteArrayOutputStream os = new ByteArrayOutputStream();
		PrintStream ps = new PrintStream(os);
		m.dump(ps, "");
		String message = os.toString();
		ps.close();
		LOGGER.debug(message);
	}
	
	private static ISOMsg createIsoMessage0200(PesoExpressReq req) throws ISOException, UnsupportedEncodingException{		
		ISOMsg request = new ISOMsg();
		request.setMTI("0200");
		request.set(3, req.getF3());
		request.set(4, req.getF4());
		request.set(7, req.getF7());
		request.set(11, req.getF11());
		request.set(12, req.getF12());
		request.set(13, req.getF13());
		request.set(22, req.getF22());
		request.set(37, req.getF37());
		request.set(41, req.getF41());
		request.set(42, req.getF42());
		request.set(43, req.getF43());
		request.set(49, req.getF49());
		request.set(76, req.getF76());
		request.set(78, req.getF78());
		return request;
	}
	
	private static ISOMsg createIsoMessage0420(PesoExpressReq req) throws ISOException, UnsupportedEncodingException{		
		ISOMsg request = new ISOMsg();
		request.setMTI("0420");
		request.set(3, req.getF3());
		request.set(4, req.getF4());
		request.set(7, req.getF7());
		request.set(11, req.getF11());
		request.set(12, req.getF12());
		request.set(13, req.getF13());
		request.set(22, req.getF22());
		request.set(37, req.getF37());
		request.set(41, req.getF41());
		request.set(42, req.getF42());
		request.set(43, req.getF43());
		request.set(49, req.getF49());
		request.set(76, req.getF76());
		request.set(78, req.getF78());
		return request;
	}
	private static ISOMsg createIsoMessage0421(PesoExpressReq req) throws ISOException, UnsupportedEncodingException{		
		ISOMsg request = new ISOMsg();
		request.setMTI("0421");
		request.set(3, req.getF3());
		request.set(4, req.getF4());
		request.set(7, req.getF7());
		request.set(11, req.getF11());
		request.set(12, req.getF12());
		request.set(13, req.getF13());
		request.set(22, req.getF22());
		request.set(37, req.getF37());
		request.set(41, req.getF41());
		request.set(42, req.getF42());
		request.set(43, req.getF43());
		request.set(49, req.getF49());
		request.set(76, req.getF76());
		request.set(78, req.getF78());
		return request;
	}
	
	
	private static PesoExpressResp createResponse(ISOMsg m){
		PesoExpressResp r = new PesoExpressResp();
		r.setF3(m.getString(3));
		r.setF4(m.getString(4));
		r.setF7(m.getString(7));
		r.setF11(m.getString(11));
		r.setF12(m.getString(12));
		r.setF13(m.getString(13));
		r.setF37(m.getString(37));
		r.setF38(m.getString(38));
		r.setF39(m.getString(39));
		r.setF41(m.getString(41));
		r.setF42(m.getString(42));
		r.setF49(m.getString(49));
		return r;
	}
	
	private static String toHex(String arg) throws UnsupportedEncodingException {
	    return String.format("%04x", new BigInteger(1, arg.getBytes("UFT-8")));
	}
	
}
